package com.wm.blog_config.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/***
 * @ClassName: SpringContext
 * @Description: spring代理对象抓取,解决事务异常
 * @Author: 半卷流年
 * @Create_time: 10:37 2020-3-23
 */
@Slf4j
@Component
public class SpringContext implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContextParam) throws BeansException {
        applicationContext = applicationContextParam;
    }

    public static Object getObject(String id) {
        Object object = null;
        object = applicationContext.getBean(id);
        return object;
    }
    /**
     * 类路径获取
     * @param tClass
     * @return
     */
    public static Object getBean(String tClass) {
        return applicationContext.getBean(tClass);
    }

    /**
     * 字节码对象获取
     * @param tClass
     * @param <T> 代理对象
     * @return
     */
    public static <T> T getBean(Class<T> tClass) {
        return applicationContext.getBean(tClass);
    }


    /**
     * 根据传入获取真实对象
     * @param beanInstance
     * @return
     */
    public static<T> T getTarget(T beanInstance) {
        if (!AopUtils.isAopProxy(beanInstance)) {
            return beanInstance;
        } else if (AopUtils.isCglibProxy(beanInstance)) {
            try {
                Field h = beanInstance.getClass().getDeclaredField("CGLIB$CALLBACK_0");
                h.setAccessible(true);
                Object dynamicAdvisedInterceptor = h.get(beanInstance);
                Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
                advised.setAccessible(true);
                T target = (T)((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
                return target;
            } catch (Exception e) {
                log.error("获取真实对象异常:{}",e.getMessage(),e);
            }
        }
        return null;
    }

}
